# /usr/bin/env python3
# coding: utf-8


import mxnet as mx
import cv2
import os
import shutil
import sys
import numpy as np
# from random import randint
from multiprocessing import Pool

if sys.platform != 'win32':
    from .core.core import MtcnnDetector
    # from core.core import MtcnnDetector
    from .core.ext import  detect_stage_warpper
    # from core.ext import  detect_stage_warpper


def main(imgpath,face_dir,face_features, num_pool, ctx, accurate_landmark, model_folder='core/model',curdir='.'):
    if sys.platform == 'win32':
        root = os.path.split(curdir)[0]
        from core.core import MtcnnDetector
        from core.ext import  detect_stage_warpper
        sys.path.append(os.path.join(root,'db'))
        from db import Chip
    pool = Pool(num_pool)
    mdr = MtcnnDetector(model_folder=model_folder, ctx=ctx, accurate_landmark=accurate_landmark, minsize=22, threshold=[0.63, 0.7, 0.85])
    totals = []
    chip_names = []
    dysize = 112
    dxsize = 92

    if not os.path.exists(imgpath):
        raise Exception('FileNotFoundError: Image path "%s" which is given not found' % imgpath)
    else:
        img = cv2.imread(imgpath)
        _ = os.path.splitext(os.path.basename(imgpath))[0]
        chip_prefix = '_'.join(['face',_,''])
        feature_prefix = '_'.join(['feature',_])

        face_dir = os.path.join(face_dir,chip_prefix)
        face_features = os.path.join(face_features,feature_prefix)
    
    try:
        faces = mdr.detect_face(img)
        for face in faces:
            lcs = pool.map(detect_stage_warpper,face)
            totals.extend(lcs)
    except Exception:
        return None
    if len(totals) != 0:
        rsls = mdr.get_faces(totals,img)
        if not rsls or len(rsls) == 0:
            if sys.platform == 'win32':
                sys.stdout.write('None')
                sys.stdout.flush()
                return
            else:
                return None

        face_boxes = rsls[0]
        face_points = rsls[1]
        chips,chip_points =  mdr.extract_image_chips(img, face_points, (dxsize,dysize), (0.32,0.42))

        for i,chip in enumerate(chips):
            chip_pathname = face_dir + str(i) + '.png'
            chip_names.append(chip_pathname)
            cv2.imwrite(chip_pathname,chip)
        
        face_points = [list(zip(face_point[:5],face_point[5:])) for face_point in face_points]

        chip_boxes = []  # chip_boxes
        chip_box_scale = (1.2,1.1)
        for face_box,face_point,chip_point in zip(face_boxes,face_points,chip_points):
            hor,ver = (face_box[2]-face_box[0],face_box[3]-face_box[1])
            ox,oy = (abs(face_box[0]-face_point[0][0]+chip_point[0][0]),
                    abs(face_box[1]-face_point[0][1]+chip_point[0][1]))
            chip_box = [int(ox),int(oy),int(ox+hor*chip_box_scale[0]),int(oy+ver*chip_box_scale[1])]
            chip_boxes.append(chip_box)

        ##### debug for rsl box
        # for box in face_boxes:
        #     cv2.rectangle(img,(int(box[0]),int(box[1])),(int(box[2]),int(box[3])),(0,255,0),1)
        # cv2.imshow('debug',img)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
        
        ##### test
        # n=1
        # chip_box = chip_boxes[n]
        # img = chips[n]
        # # face_box = face_boxes[0][:4]
        # # print(chip_box[2]-chip_box[0])
        # # print(face_box[2]-face_box[0])
        # cv2.rectangle(img,(chip_box[0],chip_box[1]),(chip_box[2],chip_box[3]),(255,0,0),2)
        # # cv2.rectangle(img,(int(face_box[0]),int(face_box[1])),(int(face_box[2]),int(face_box[3])),(255,0,0),2)
        # cv2.imshow('chip',img)
        # # cv2.imshow('image',img)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
        # end
        np.savez_compressed(face_features,chip_names=chip_names,chip_points=chip_points,chip_boxes=chip_boxes,face_boxes=face_boxes,face_points=face_points,imgpath=imgpath)

        featurefile=face_features+'.npz'
        for i in range(len(chip_names)):
            chip = Chip(chip=chip_names[i],source=imgpath,feature=featurefile)
            chip.save()

        output = dict(faces=chip_names,featurefile=featurefile)
        if sys.platform == 'win32':
            import json
            output = json.dumps(output)
            sys.stdout.write(output)
            sys.stdout.flush()
        else:
            return output
    else:
        # print('[QAQ] Non face has been detected in image file: %s' % imgpath)
        if sys.platform == 'win32':
            sys.stdout.write('None')
            sys.stdout.flush()
        return None


if __name__ == '__main__':
    cur = os.path.dirname(__file__)
    import getopt
    if len(sys.argv[1:]) < 6:
        raise Exception('\n\tParameters "imgpath","face_dir","face_features","num_pool","accurate_landmark","ctx" must be given.')
    options,args = getopt.getopt(sys.argv[1:],
                "i:f:F:n:k:c:",
                ['imgpath=','face_dir=','face_features=','num_pool=','accurate_landmark=','ctx='])
    
    for name,value in options:
        if name in ('-i','--imgpath'):
            imgpath = str(value)
        if name in ('-f','--face_dir'):
            face_dir = str(value)
        if name in ('-F','--face_features'):
            face_features = str(value)
        if name in ('-n','--num_pool'):
            num_pool = int(value)
        if name in ('-k','--accurate_landmark'):
            accurate_landmark = True if str(value).lower() == 'true' else False  
        if name in ('-c','--ctx'):
            if str().lower() == 'cpu':
                ctx = mx.cpu()
            else:
                ctx = mx.gpu()
    model_folder = os.path.join(cur,'core','model')
    main(imgpath,face_dir=face_dir,face_features=face_features,num_pool=4,accurate_landmark=False,ctx=mx.gpu(),model_folder=model_folder,curdir=cur)

    ###### debug
    ###
    # # # print(os.path.exists(face_features))
    # cv2.rectangle(draw, (int(b[0]), int(b[1])), (int(b[2]), int(b[3])), (255, 255, 255))
    # cv2.circle(draw, (p[i], p[i + 5]), 1, (0, 0, 255), 2)


    
